#ifndef _KLAS_RENDERABLE_HPP_
#define _KLAS_RENDERABLE_HPP_

#include "../Platform.hpp"
#include "../math/Vector2.hpp"
#include "Transformation.hpp"
#include "RenderingCore.hpp"

#include "../../external/boost/smart_ptr.hpp"
#include <vector>
using std::vector;

namespace klas
{
  namespace graphics
  {

    //! Any object that can be rendered is derived from Renderable.
    class KLAS_API Renderable
    {
    public:

      //! Default ctor
      Renderable() {}

      //! Registers the renderable into the scene.
      /*! Derived classes ctor MUST call Renderable(this); */
      Renderable(Renderable *thisPtr);
      
      //! Removes this object from the scene.
      virtual ~Renderable();

      //! Change the rotation of the renderable object.
      /*! \sa setTransformation */
      void setRot(double degrees);
      
      //! Change the size of the renderable object.
      /*! \param size The size of the position.  X size / Y size.
          \sa setTransformation */
      void setSize(const math::Vector2d &size);

      //! Changes the size of the object.
      /*! \param sizeX The horizontal scaling factor.
          \param sizeY The vertical scaling factor. */
      void setSize(double sizeX, double sizeY);

      //! Changes the size of the object.
      /*! \param size The size of the object.  The x and y size are set to this value.
          \sa setTransformation */
      void setSize(double size);

      //! Change the objects horizontal size.
      /*! \sa setTransformation */
      void setSizeX(double size);

      //! Change the object's vertical size.
      /*! \sa setTransformation */
      void setSizeY(double size);

      //! Sets the position of the renderable object.
      /*! \sa setTransformation */
      void setPos(double x, double y);

      //! Sets the position of the renderable object.
      /*! \param pos A vector2<double> describing the object's position. 
          \sa setTransformation */
      void setPos(const math::Vector2d &pos);

      //! Sets the transformation of the renderable object.
      /*! \param transform The new transformation for the renderable object.
          \sa getTransformation */
      void setTransformation(const Transformation& transform);

      //! Sets the layer for the renderable object to render on.  Layer 0 is on top, then layer 1...
      void setRenderingLayer(uint16 layer);

      /* ------------------------------------------------------------------- */
      /* ------------------------------------------------------------------- */

      //! Gets the rotation of the renderable object.
      double getRot() const;

      //! Gets the size of the renderable object.
      math::Vector2d& getSize();

      //! Gets the objects horizontal size.
      double getSizeX() const;

      //! Gets the object's vertical size.
      double getSizeY() const;

      //! Gets the position of the renderable object.
      math::Vector2d& getPos();

      //! Gets the x position of the renderable object.
      double getX() const;

      //! Gets the y position of the renderable object.
      double getY() const;

      //! Gets the transformation of the renderable object.
      Transformation getTransformation() const;
      
      //! Gets the rendering layer of the renderable object.
      uint16 getRenderingLayer() const;

      /* ------------------------------------------------------------------- */
      /* ------------------------------------------------------------------- */

      //! Add a child to this renderable object.
      void addChild(Renderable *child);

      //! Get a reference to the vector of this renderable object's children.
      vector<Renderable*>& getChildren();

      /* ------------------------------------------------------------------- */
      /* ------------------------------------------------------------------- */

      //! Moves the position of the renderable object by the offset.  Could also be called translate.
      void translate(const math::Vector2d &offset);

      //! Moves the position of the renderable object by the offset.  Could also be called translate.
      void translate(double x, double y);

      /* ------------------------------------------------------------------- */
      /* ------------------------------------------------------------------- */

      //! Renders the renderable object, along with all of its children.
      /*! \param core The rendering core to render into. */
      void render(RenderingCore* core);

      //! Changes the transparency of the object.  This is independent of the color.  It is the entire polygon's alpha.
      /*! \param transparency The transparency of the object.  Takes a value between 0 and 255, or 0 and 1.
          \sa getTransparency */
      void setTransparency(double transparency);

      //! Gets the alpha of the object.
      double getTransparency() const;

    protected:
      
      //! Internal.  Renders only this element, and ignores all children.
      /*! \param core The rendering core to render into.
          \param origin Where 0,0 is positioned. */
      virtual void renderElement(RenderingCore* core, const math::Vector2d& origin) = 0;

      Transformation m_transform; //!< Position, location, and rotation of the object.

      uint16 m_renderingLayer;    //!< The layer the renderable renders on.

      double m_transparency;      //!< The transparency of the renderable object.

      vector<Renderable*> m_children; //!< The children of the renderable object, possibly empty.
    };

  }
}

#endif